package com.xiaozhen.modbus.serial;

import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.msg.WriteCoilRequest;
import com.serotonin.modbus4j.serial.rtu.RtuMessageRequest;
import com.xiaozhen.common.core.utils.ByteArrayUtil;
import gnu.io.*;

import java.util.List;
import java.util.TooManyListenersException;

/**
 * @name: SerialPortUtilTest
 * @author: tuacy.
 * @date: 2019/6/26.
 * @version: 1.0
 * @Description: 串口测试代码
 */
public class SerialPortUtilTest {

    public static void main(String[] args) {
        SerialPortUtilTest serialPortUtilTest = new SerialPortUtilTest();
        serialPortUtilTest.rtuTcpAction();
    }

    /**
     * 测试获取串口列表
     */
    public void getSystemPortList() {

        List<String> portList = SerialPortUtil.getSerialPortList();
        System.out.println(portList);

    }

    /**
     * 测试 MODBUS RTU TCP打开，读，写操作
     */
    public void rtuTcpAction() {
        try {
            final ModbusMaster modbusMaster = getMaster("127.0.0.1", 503);
            //启动一个线程每2s向串口发送数据，发送1000次hello
            new Thread(() -> {
                int i = 1;
                while (i < 1000) {
                    try {
                        WriteCoilRequest coilRequest = new WriteCoilRequest(1, 2, true);
                        modbusMaster.send(coilRequest);//发送数据
                        i++;
                        Thread.sleep(2000);
                    } catch (ModbusTransportException e) {
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            try {
                // sleep 一段时间保证线程可以执行完
                Thread.sleep(3 * 30 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch ( ModbusInitException e) {
            e.printStackTrace();
        }
    }


    /**
     * 测试串口打开，读，写操作
     */
    public void serialPortAction() {
        try {
            final SerialPort serialPort = SerialPortUtil.openSerialPort("COM2", 115200);
            //启动一个线程每2s向串口发送数据，发送1000次hello
            new Thread(() -> {
                int i = 1;
                while (i < 1000) {
                    try {
                        WriteCoilRequest coilRequest = new WriteCoilRequest(1, 2, true);
                        RtuMessageRequest rtuMessageRequest = new RtuMessageRequest(coilRequest);
                        SerialPortUtil.sendData(serialPort, rtuMessageRequest.getMessageData());//发送数据
                        i++;
                        Thread.sleep(2000);
                    } catch (ModbusTransportException e) {
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            //设置串口的listener
            SerialPortUtil.setListenerToSerialPort(serialPort, event -> {
                //数据通知
                if (event.getEventType() == SerialPortEvent.DATA_AVAILABLE) {
                    byte[] bytes = SerialPortUtil.readData(serialPort);
                    System.out.println("收到的数据长度：" + bytes.length);
                    System.out.println("收到的数据：" + ByteArrayUtil.bytes2HexStr(bytes));
                }
            });
            try {
                // sleep 一段时间保证线程可以执行完
                Thread.sleep(3 * 30 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (NoSuchPortException | PortInUseException | UnsupportedCommOperationException | TooManyListenersException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取 Modbus Master
     *
     * @param host 主机
     * @param port 端口号
     * @return ModbusMaster
     * @throws ModbusInitException ModbusInitException
     */
    public ModbusMaster getMaster(String host, int port) throws ModbusInitException {
        IpParameters params = new IpParameters();
        params.setHost(host);
        params.setPort(port);
        ModbusMaster modbusMaster = new ModbusFactory().createUdpMaster(params);
        modbusMaster.init();
        return modbusMaster;
    }
}
